package cn.dansj.utils.interfaces;

import cn.dansj.common.utils.enums.ResponseCode;
import cn.dansj.common.springboot.reflect.Advice;
import cn.dansj.common.springboot.reflect.ProxyFactory;
import cn.dansj.common.springboot.reflect.SpringDependencyInjectionUtils;
import cn.dansj.common.utils.transfer.Transformation;
import cn.dansj.exception.InterfaceResponseException;
import cn.dansj.handler.Interface;
import groovy.lang.GroovyClassLoader;

import java.lang.reflect.Method;

public class InterfaceFactory {
    private static final InterfaceAdvice interfaceAdvice = new InterfaceAdvice();

    /**
     * groovy class loader
     */
    private static final GroovyClassLoader groovyClassLoader = new GroovyClassLoader();

    /**
     * load new instance, prototype
     */
    public static Interface loadNewInstance(String codeSource) throws Exception {
        if (codeSource != null && !codeSource.trim().isEmpty()) {
            Class<?> clazz = groovyClassLoader.parseClass(codeSource);
            if (clazz != null) {
                final Object instance = SpringDependencyInjectionUtils.newInstance(clazz);
                if (instance instanceof Interface interfaceHandler) {
                    return ProxyFactory.createProxy(interfaceHandler, interfaceAdvice);
                } else {
                    throw new IllegalArgumentException("load new instance error, cannot convert from instance[" + instance.getClass() + "] to " + Interface.class);
                }
            }
        }
        throw new IllegalArgumentException("load new instance error, instance source code is null");
    }

    public static class InterfaceAdvice implements Advice {
        @Override
        public Throwable exception(Method m, Object[] args, Throwable throwable) {
            final Throwable baseException = Transformation.getBaseException(throwable);
            return baseException instanceof InterfaceResponseException ? baseException : new InterfaceResponseException(ResponseCode.RunTimeError.getStatusCode(), baseException.getMessage());
        }
    }
}